/*
 * Copyright (C), 2002-2016, 苏宁易购电子商务有限公司
 * FileName: MySQLClusterAction.java
 * Author:   admin
 * Date:     2016年3月1日 下午5:27:33
 * Description: //模块目的、功能描述      
 * History: //修改记录
 * <author>      <time>      <version>    <desc>
 * 修改人姓名             修改时间            版本号                  描述
 */
package com.suning.app.snpaasadmin.action;

import com.opensymphony.xwork2.ActionSupport;
import com.suning.app.snpaasadmin.api.ComponentApi;
import com.suning.app.snpaasadmin.api.DeploymentApi;
import com.suning.app.snpaasadmin.domain.ComponentConfig;
import com.suning.app.snpaasadmin.domain.MysqlClusterDetail;
import com.suning.app.snpaasadmin.domain.MysqlClusterInfo;
import com.suning.app.snpaasadmin.domain.ServiceBrokerInfo;
import com.suning.app.snpaasadmin.operation.AppEnvironmentDBOperation;
import com.suning.app.snpaasadmin.operation.CfClusterDBOperation;
import com.suning.app.snpaasadmin.pojo.CfApp;
import com.suning.app.snpaasadmin.pojo.CfCluster;
import com.suning.app.snpaasadmin.pojo.CfClusterConfig;
import com.suning.app.snpaasadmin.pojo.CfMysqlCluster;
import com.suning.app.snpaasadmin.pojo.CfMysqlClusterConfig;
import com.suning.app.snpaasadmin.pojo.CfMysqlServiceBrokers;
import com.suning.app.snpaasadmin.pojo.ServiceBrokerMysql;
import com.suning.app.snpaasadmin.util.Constants;
import com.suning.app.snpaasadmin.util.JsonUtil;
import com.suning.app.snpaasadmin.util.StringUtil;

import java.net.InetAddress;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.apache.http.HttpHost;
import org.apache.http.protocol.HttpContext;
import org.apache.log4j.Logger;
import org.apache.struts2.ServletActionContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

/**
 * mysql集群部署<br>
 * 〈功能详细描述〉
 *
 * @author admin
 * @see [相关类/方法]（可选）
 * @since [产品/模块版本] （可选）
 */
@Controller
public class MySQLClusterAction extends ActionSupport {

    /**
     */
    private static final long serialVersionUID = 1L;
    
    private Logger logger = Logger.getLogger(MySQLClusterAction.class);

    private Map<String, Object> dataMap;

    private String directorUuid;

    private String componentDomain;

    private String networkId;

    private String components;

    private String deployId;

    private String deploymentName;

    private String storageMb;

    private String mysqlClusterId;

    private String cfMysql;

    private String clusterName;

    @Autowired
    private CfClusterDBOperation clusterDB;

    public String saveMysqlConfig() throws Exception {
        dataMap = new HashMap<String, Object>();
        CfMysqlCluster mysqlCluster = new CfMysqlCluster();
        mysqlCluster.setDeployId(Integer.valueOf(deployId));
        mysqlCluster.setClusterName(deploymentName);
        mysqlCluster.setComponentDomain(componentDomain);
        mysqlCluster.setDirectorUuid(directorUuid);
        mysqlCluster.setNetworkId(networkId);
        mysqlCluster.setStorageMb(storageMb);
        mysqlCluster.setCfMysqlVersion(cfMysql);
        mysqlCluster.setStatus(Constants.CLUSTER_UNDEPLOY);
        if (StringUtil.isNotEmpty(mysqlClusterId) && StringUtil.isNotNullString(mysqlClusterId)) {

            // 覆盖mysqlClusterId下的配置
            mysqlCluster.setId(Integer.valueOf(mysqlClusterId));
            mysqlCluster.setUpdateTime(new Date());
            clusterDB.updataMysqlConfig(mysqlCluster);

            // 查询所有的组件 更新
            List<CfMysqlClusterConfig> configs = clusterDB.selectMysqlConfig(mysqlClusterId);
            if (configs != null && configs.size() > 0) {
                for (CfMysqlClusterConfig comConfig : configs) {
                    List<Map<String, Object>> temp = JsonUtil.convertJsonToList(components);
                    for (Map<String, Object> oneConfig : temp) {
                        if (comConfig.getName().equals(oneConfig.get("name").toString())) {
                            comConfig.setCount(Integer.valueOf(oneConfig.get("count").toString()));
                            comConfig.setCpuCore(Integer.valueOf(oneConfig.get("cpuCore").toString()));
                            comConfig.setCpuOverload(Boolean.valueOf(oneConfig.get("overload").toString()));
                            comConfig.setMemorySize(oneConfig.get("memory").toString());
                            comConfig.setNetId(oneConfig.get("netId").toString());
                            clusterDB.updateMysqlComConfig(comConfig);
                        }
                    }
                }
            }
            Map<String, String> map = new HashMap<>();
            map.put("mysqlClusterId", mysqlClusterId);
            dataMap.put("data", map);
            dataMap.put("success", true);
            return SUCCESS;
        } else {
            mysqlCluster.setCreateTime(new Date());

            // 查询rootdomain 根据deployId
            CfCluster cfCluster = clusterDB.selectCfCluster(deployId);
            String cfRootDomain = cfCluster.getRootDomain();
            mysqlCluster.setRootDomain(cfRootDomain);
            clusterDB.insertMysqlCluster(mysqlCluster);
            Integer clusterId = mysqlCluster.getId();
            List<Map<String, Object>> temp = JsonUtil.convertJsonToList(components);
            for (Map<String, Object> oneConfig : temp) {
                CfMysqlClusterConfig cMysqlClusterConfig = new CfMysqlClusterConfig();
                cMysqlClusterConfig.setName(oneConfig.get("name").toString());
                cMysqlClusterConfig.setCount(Constants.MYSQL_COUNT);
                cMysqlClusterConfig.setCpuCore(Integer.valueOf(oneConfig.get("cpuCore").toString()));
                cMysqlClusterConfig.setCpuOverload(Boolean.valueOf(oneConfig.get("overload").toString()));
                cMysqlClusterConfig.setMemorySize(oneConfig.get("memory").toString());

                // 从cf集群获取networkId
                cMysqlClusterConfig.setNetId(cfCluster.getNetworkId());
                cMysqlClusterConfig.setMysqlClusterId(clusterId);
                clusterDB.insertMysqlComConfig(cMysqlClusterConfig);
            }
            Map<String, String> map = new HashMap<>();
            map.put("mysqlClusterId", clusterId.toString());
            dataMap.put("data", map);
            dataMap.put("success", true);
        }
        return SUCCESS;
    }

    public String createMysqlCluster() throws Exception {
        dataMap = new HashMap<String, Object>();
        Map<String, Object> input = new HashMap<String, Object>();
        HttpServletRequest request = ServletActionContext.getRequest();
        HttpSession session = request.getSession();
        HttpContext httpContext = (HttpContext) session.getAttribute(LoginAction.CFBASICAUTH);
        HttpHost httpHost = (HttpHost) session.getAttribute(LoginAction.CFAUTHHOST);

        // 根据传入的mysqlClusterId查询数据
        List<CfMysqlClusterConfig> configs = clusterDB.selectMysqlConfig(mysqlClusterId);
        CfMysqlCluster mysqlCluster = clusterDB.selectMysqlCluster(mysqlClusterId);
        if (mysqlCluster != null) {
            input.put("director_uuid", mysqlCluster.getDirectorUuid());
            input.put("cf_mysql", mysqlCluster.getCfMysqlVersion());
            input.put("deployment_name", mysqlCluster.getClusterName());
            input.put("root_domain", mysqlCluster.getRootDomain());
            input.put("component_domain", mysqlCluster.getComponentDomain());
            input.put("network_id", mysqlCluster.getNetworkId());
            input.put("storage_mb", mysqlCluster.getStorageMb());

            // 根据deployId获取集群信息
            CfCluster cluster = clusterDB.selectCfCluster(mysqlCluster.getDeployId().toString());
            input.put("cf_deployment_name", cluster.getClusterName());
            input.put("root_domain", cluster.getRootDomain());

            List<CfClusterConfig> cfClusterConfigs = clusterDB.selectComponentConfig(cluster.getId().toString(),
                    Constants.NATS);
            if (cfClusterConfigs != null && cfClusterConfigs.size() > 0) {
                input.put("nats_size", cfClusterConfigs.get(0).getCount());
            }
        }
        if (configs != null && configs.size() > 0) {
            for (CfMysqlClusterConfig config : configs) {
                input.put(config.getName(), config);
            }
        }
        
        ServletContext sc = ServletActionContext.getServletContext();
        String filePath = DeploymentApi.generateyml(input, Constants.MYSQL_CLUSTER, logger , sc);
        logger.fatal("Yaml filePath:"+filePath);
        mysqlCluster.setFilePath(filePath);
        clusterDB.updataMysqlConfig(mysqlCluster);
        String data = DeploymentApi.getyml(filePath);
        String taskId = DeploymentApi.deployCluster(httpContext, httpHost, data);

        clusterDB.insertTaskId(taskId, deployId, Constants.TYPE_MYSQL_VERSION);
        // 更新部署状态
        mysqlCluster.setStatus(Constants.CLUSTER_DEPLOY);
        mysqlCluster.setTaskId(taskId);
        clusterDB.updataMysqlConfig(mysqlCluster);
        Map<String, String> map = new HashMap<>();
        map.put("taskId", taskId);
        dataMap.put("data", map);
        dataMap.put("success", true);
        return SUCCESS;
    }

    public String createServiceBroker() throws Exception {
        CfMysqlCluster mysqlCluster = clusterDB.selectMysqlCluster(mysqlClusterId);
        String brokerUrl = "http://" + mysqlCluster.getClusterName() + "." + mysqlCluster.getRootDomain();
        Map<String, String> params = new HashMap<>();
        params.put("name", mysqlCluster.getClusterName() + "_" + mysqlCluster.getStorageMb());
        params.put("broker_url", brokerUrl);
        params.put("auth_username", Constants.BROKER_AUTH_USERNAME);
        params.put("auth_password", Constants.BROKER_AUTH_PASSWORD);
        InetAddress address = InetAddress.getByName("0.proxy.default." + mysqlCluster.getClusterName() + ".microbosh");
        String brokerGuid = DeploymentApi.createServiceBroker(mysqlCluster.getRootDomain(), params);

        // 将该broker下的plan设置为可见
        String mysqlIP = address.getHostAddress();

        // 存入用户portal数据库
        CfMysqlServiceBrokers broker = new CfMysqlServiceBrokers();
        broker.setServiceBrokerGuid(brokerGuid);
        broker.setUseState("0");
        broker.setServiceBrokerIp(mysqlIP);
        broker.setDisk(null);
        broker.setMemory(null);
        clusterDB.insertServiceBroker(broker);

        ServiceBrokerMysql serviceBrokr = new ServiceBrokerMysql();
        serviceBrokr.setServiceBrokeGuid(brokerGuid);
        serviceBrokr.setMysqlId(Integer.valueOf(mysqlClusterId));
        clusterDB.insertAdminServiceBroker(serviceBrokr);
        return SUCCESS;
    }

    public String listMysqlCluster() throws Exception {
        dataMap = new HashMap<String, Object>();
        logger.fatal("开始");
        HttpServletRequest request = ServletActionContext.getRequest();
        HttpSession session = request.getSession();
        HttpContext httpContext = (HttpContext) session.getAttribute(LoginAction.CFBASICAUTH);
        HttpHost httpHost = (HttpHost) session.getAttribute(LoginAction.CFAUTHHOST);
        
        // 列出所有的集群
        List<Map<String, Object>> deploys = DeploymentApi.getDeployments(httpContext, httpHost,logger);
       
        // 从数据库中获取指定集群
        List<CfMysqlCluster> mysqlClusters = clusterDB.selectAllMysqlCluster();
        List<MysqlClusterInfo> results = new ArrayList<>();
        if (deploys != null) {
            Map<String, Object> tmpMap = new HashMap<>();
            for (CfMysqlCluster cluster : mysqlClusters) {

                if (tmpMap.containsKey(cluster.getClusterName())) {
                    continue;
                }
                for (Map<String, Object> map : deploys) {

                    if (cluster.getClusterName().equals(map.get("name").toString())) {

                        // 查找集群状态
                        Map<String, Object> vms = ComponentApi.getVms(httpContext, httpHost, cluster.getClusterName());
                        // 根据taskId获取到状态
                        Integer taskId = (Integer) vms.get("id");
                        boolean flag = false;
                        while (!flag) {
                            Map<String, Object> tasks = ComponentApi.getTasks(httpContext, httpHost, taskId);
                            if (tasks.get("state").toString().equals("done")) {
                                flag = true;
                            }
                        }
                        if (flag == true) {
                            MysqlClusterInfo mysqlClusterInfo = new MysqlClusterInfo();
                            // boolean state = DeploymentApi.getClusterState(httpContext, httpHost, taskId);
                            mysqlClusterInfo.setDeployId(cluster.getId().toString());
                            mysqlClusterInfo.setCfDeployId(cluster.getDeployId().toString());
                            if (cluster.getCreateTime() != null) {
                                mysqlClusterInfo.setCreateTime(cluster.getCreateTime().getTime());
                            }
                            if (cluster.getUpdateTime() != null) {
                                mysqlClusterInfo.setUpdateTime(cluster.getUpdateTime().getTime());
                            }
                            mysqlClusterInfo.setMysqlClusterName(cluster.getClusterName());

                            // 根据cfdeployId获取集群名称
                            mysqlClusterInfo
                                    .setCfClusterName(clusterDB.getDeployName(cluster.getDeployId().toString()));
                            /*
                             * if(state==false) { mysqlClusterInfo.setMysqlStatus(Constants.CLUSTER_ERROR); } else {
                             * mysqlClusterInfo.setMysqlStatus(cluster.getStatus()); }
                             */
                            mysqlClusterInfo.setMysqlStatus(cluster.getStatus());

                            // 查询对应的broker的状态 是否使用
                            String guid = clusterDB.selectServiceBrokerUse(cluster.getId());
                            logger.fatal(guid);
                            if (StringUtil.isNotEmpty(guid)) {
                               /* boolean usage = clusterDB.getBrokerUsage(guid);
                                if (usage == false) {
                                    mysqlClusterInfo.setBrokerStatus(Integer.valueOf(Constants.SERVICE_BROKER_UNUSE));
                                } else {
                                    mysqlClusterInfo.setBrokerStatus(Integer.valueOf(Constants.SERVICE_BROKER_USAGE));
                                }*/
                                mysqlClusterInfo.setBrokerStatus(Integer.valueOf(Constants.SERVICE_BROKER_USAGE));
                            } else {
                                mysqlClusterInfo.setBrokerStatus(Integer.valueOf(Constants.SERVICE_BROKER_UNUSE));
                            }
                            tmpMap.put(cluster.getClusterName(), mysqlClusterInfo);
                        }
                    }
                }
                if (tmpMap.containsKey(cluster.getClusterName())) {
                    continue;
                }
                MysqlClusterInfo mysqlClusterInfo = new MysqlClusterInfo();
                mysqlClusterInfo.setDeployId(cluster.getId().toString());
                mysqlClusterInfo.setCfDeployId(cluster.getDeployId().toString());
                if (cluster.getCreateTime() != null) {
                    mysqlClusterInfo.setCreateTime(cluster.getCreateTime().getTime());
                }
                if (cluster.getUpdateTime() != null) {
                    mysqlClusterInfo.setUpdateTime(cluster.getUpdateTime().getTime());
                }
                mysqlClusterInfo.setMysqlClusterName(cluster.getClusterName());

                // 根据cfdeployId获取集群名称
                mysqlClusterInfo.setCfClusterName(clusterDB.getDeployName(cluster.getDeployId().toString()));
                mysqlClusterInfo.setMysqlStatus(cluster.getStatus());
                tmpMap.put(cluster.getClusterName(), mysqlClusterInfo);
            }

            // 遍历map
            for (Object value : tmpMap.values()) {
                results.add((MysqlClusterInfo) value);
            }
            dataMap.put("data", results);
            dataMap.put("success", true);
        }
        return SUCCESS;
    }

    public String getDetail() throws Exception {
        dataMap = new HashMap<String, Object>();
        /*
         * HttpServletRequest request = ServletActionContext.getRequest(); HttpSession session = request.getSession();
         * HttpContext httpContext = (HttpContext) session.getAttribute(LoginAction.CFBASICAUTH); HttpHost httpHost =
         * (HttpHost) session.getAttribute(LoginAction.CFAUTHHOST);
         */

        // 从数据库中获取指定集群
        CfMysqlCluster mysqlCluster = clusterDB.selectMysqlCluster(mysqlClusterId);
        MysqlClusterDetail mysqlDetail = new MysqlClusterDetail();
        mysqlDetail.setCfMysql(mysqlCluster.getCfMysqlVersion());
        mysqlDetail.setComponentDomain(mysqlCluster.getComponentDomain());
        mysqlDetail.setDeployId(mysqlCluster.getId().toString());
        mysqlDetail.setDeploymentName(mysqlCluster.getClusterName());
        mysqlDetail.setDirectorUuid(mysqlCluster.getDirectorUuid());
        mysqlDetail.setNetworkId(mysqlCluster.getNetworkId());
        mysqlDetail.setRootDomain(mysqlCluster.getRootDomain());
        mysqlDetail.setStorageMb(mysqlCluster.getStorageMb());

        // 根据cf集群id获取
        CfCluster cfCluster = clusterDB.selectCfCluster(mysqlCluster.getDeployId().toString());
        mysqlDetail.setRuningtimeDomain(cfCluster.getRuningtimeDomain());
        mysqlDetail.setCfClusterName(cfCluster.getClusterName());

        // 列出所有的集群
        // List<Map<String, Object>> deploys = DeploymentApi.getDeployments(httpContext, httpHost);

        // 获取组件mysql详情
        List<CfMysqlClusterConfig> coms = clusterDB.selectMysqlConfig(mysqlClusterId);
        List<ComponentConfig> comConfigs = new ArrayList<>();
        if (coms != null && coms.size() > 0) {
            for (CfMysqlClusterConfig comConfig : coms) {
                ComponentConfig config = new ComponentConfig();
                config.setCount(comConfig.getCount());
                config.setName(comConfig.getName());
                config.setCpuCore(comConfig.getCpuCore());
                config.setOverload(Boolean.valueOf(comConfig.getCpuOverload()));
                config.setMemory(comConfig.getMemorySize());
                config.setNetId(comConfig.getNetId());
                comConfigs.add(config);
            }
        }
        mysqlDetail.setComponents(comConfigs);

        // 获取serviceBroker
        ServiceBrokerInfo serviceBrokerInfo = new ServiceBrokerInfo();
        String guid = clusterDB.selectServiceBrokerUse(Integer.valueOf(mysqlClusterId));
        if (StringUtil.isNotNullString(guid) && StringUtil.isNotEmpty(guid)) {
            CfMysqlServiceBrokers serviceBroker = clusterDB.getServiceBrokerDetail(guid);
            serviceBrokerInfo.setDisk(serviceBroker.getDisk());
            serviceBrokerInfo.setMemory(serviceBroker.getMemory());
            serviceBrokerInfo.setIp(serviceBroker.getServiceBrokerIp());
            serviceBrokerInfo.setUserId(serviceBroker.getUserId());
            serviceBrokerInfo.setServiceBrokerGuid(guid);
            

            // 根据usestate和instanceId获取app
            if (Constants.SERVICE_BROKER_USAGE.equals(serviceBroker.getUseState())) {
                AppEnvironmentDBOperation envOp = new AppEnvironmentDBOperation();
                CfApp app = envOp.getApp(serviceBroker.getInstanceId());
                serviceBrokerInfo.setAppId(app.getId());
                serviceBrokerInfo.setAppName(app.getAppName());
                serviceBrokerInfo.setStatus("已使用");
            } else {
                serviceBrokerInfo.setStatus("未使用");
            }
        }
        mysqlDetail.setServiceBroker(serviceBrokerInfo);
        dataMap.put("data", mysqlDetail);
        dataMap.put("success", true);
        return SUCCESS;
    }

    public String deleteMysqlCluster() throws Exception {
        dataMap = new HashMap<String, Object>();
        HttpServletRequest request = ServletActionContext.getRequest();
        HttpSession session = request.getSession();
        HttpContext httpContext = (HttpContext) session.getAttribute(LoginAction.CFBASICAUTH);
        HttpHost httpHost = (HttpHost) session.getAttribute(LoginAction.CFAUTHHOST);
        CfMysqlCluster mysqlCluster = clusterDB.selectMysqlCluster(mysqlClusterId);
        String serviceBrokerUuid = clusterDB.selectServiceBrokerUse(mysqlCluster.getId());
        if (!serviceBrokerUuid.equals("")) {
            DeploymentApi.deleteServiceBroker(serviceBrokerUuid, mysqlCluster.getRootDomain());
        }
        DeploymentApi.deleteMysqlCluster(httpContext, httpHost, mysqlCluster.getClusterName());
        clusterDB.deleteMysqlData(mysqlClusterId);
        dataMap.put("success", true);
        return SUCCESS;
    }

    public String checkName() throws Exception {
        dataMap = new HashMap<String, Object>();
        Boolean isDup = true;
        List<CfMysqlCluster> mysqlClusters = clusterDB.selectAllMysqlCluster();
        for (CfMysqlCluster cluster : mysqlClusters) {
            if (clusterName.equals(cluster.getClusterName())) {
                isDup = false;
            }
        }
        dataMap.put("data", isDup);
        dataMap.put("success", true);
        return SUCCESS;
    }

    /**
     * @return the dataMap
     */
    public Map<String, Object> getDataMap() {
        return dataMap;
    }

    /**
     * @param dataMap the dataMap to set
     */
    public void setDataMap(Map<String, Object> dataMap) {
        this.dataMap = dataMap;
    }

    /**
     * @return the directorUuid
     */
    public String getDirectorUuid() {
        return directorUuid;
    }

    /**
     * @param directorUuid the directorUuid to set
     */
    public void setDirectorUuid(String directorUuid) {
        this.directorUuid = directorUuid;
    }

    /**
     * @return the componentDomain
     */
    public String getComponentDomain() {
        return componentDomain;
    }

    /**
     * @param componentDomain the componentDomain to set
     */
    public void setComponentDomain(String componentDomain) {
        this.componentDomain = componentDomain;
    }

    /**
     * @return the networkId
     */
    public String getNetworkId() {
        return networkId;
    }

    /**
     * @param networkId the networkId to set
     */
    public void setNetworkId(String networkId) {
        this.networkId = networkId;
    }

    /**
     * @return the components
     */
    public String getComponents() {
        return components;
    }

    /**
     * @param components the components to set
     */
    public void setComponents(String components) {
        this.components = components;
    }

    /**
     * @return the deployId
     */
    public String getDeployId() {
        return deployId;
    }

    /**
     * @param deployId the deployId to set
     */
    public void setDeployId(String deployId) {
        this.deployId = deployId;
    }

    /**
     * @return the deploymentName
     */
    public String getDeploymentName() {
        return deploymentName;
    }

    /**
     * @param deploymentName the deploymentName to set
     */
    public void setDeploymentName(String deploymentName) {
        this.deploymentName = deploymentName;
    }

    /**
     * @return the mysqlClusterId
     */
    public String getMysqlClusterId() {
        return mysqlClusterId;
    }

    /**
     * @param mysqlClusterId the mysqlClusterId to set
     */
    public void setMysqlClusterId(String mysqlClusterId) {
        this.mysqlClusterId = mysqlClusterId;
    }

    /**
     * @return the cfMysql
     */
    public String getCfMysql() {
        return cfMysql;
    }

    /**
     * @param cfMysql the cfMysql to set
     */
    public void setCfMysql(String cfMysql) {
        this.cfMysql = cfMysql;
    }

    /**
     * @return the storageMb
     */
    public String getStorageMb() {
        return storageMb;
    }

    /**
     * @param storageMb the storageMb to set
     */
    public void setStorageMb(String storageMb) {
        this.storageMb = storageMb;
    }

    /**
     * @return the clusterName
     */
    public String getClusterName() {
        return clusterName;
    }

    /**
     * @param clusterName the clusterName to set
     */
    public void setClusterName(String clusterName) {
        this.clusterName = clusterName;
    }

}
